package com.sky.websocket;

import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 */
@Component
@ServerEndpoint("/ws/{sid}") //与Controller类似，也是根据路径进行匹配，但是在javax.websocket.server包下
public class WebSocketServer {
    /**
     * 实现步骤：
     * 1.直接使用websocket.html页面作为WebSocket客户端
     * 2.导入WebSocket的maven坐标
     * 3.导入WebSocket服务端组件WebSocketServer，用于和客户端通信
     * 4.导入配置类WebSocketConfiguration，注册WebSocket的服务端组件
     * 5.导入定时任务类WebSocketTask，定时向客户端推送数据
     */
    //握手： ws://localhost/ws/eirku6j1jfg ，但是这次请求是请求nginx，通过反向代理到tomcat

    //存放会话对象，建立的连接本质上是会话Session javax.websocket
    private static final Map<String, Session> sessionMap = new HashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen // 加上这个注解，当前的方法就变成了回调方法
    public void onOpen(Session session, @PathParam("sid") String sid) { //客户端可能有多个呀，是通过sid区分的
        System.out.println("客户端：" + sid + "建立连接");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法，与controller方法类似
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端：" + sid + "的信息:" + message);
    }

    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发，需要手动取调用这个方法
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息，这句代码就是
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
